# -*- coding: utf-8 -*-
# @Time    : 2024/7/3 15:48
# @Author  : yujiahao
# @File    : 00_whats_fastapi.py
# @description:初始fasterapi
"""
1. 什么是 FastAPI:
FastAPI 是一个用于构建 API 的现代、快速（高性能）的 web 框架，使用 Python 3.6+ 并基于标准的 Python 类型提示。

关键特性:
- 快速：可与 NodeJS 和 Go 比肩的极高性能（归功于 Starlette 和 Pydantic）。最快的 Python web 框架之一。
- 高效编码：提高功能开发速度约 200％ 至 300％。
- 更少 bug：减少约 40％ 的人为（开发者）导致错误。
- 智能：极佳的编辑器支持。处处皆可自动补全，减少调试时间。
- 简单：设计的易于使用和学习，阅读文档的时间更短。
- 简短：使代码重复最小化。通过不同的参数声明实现丰富功能。bug 更少。
- 健壮：生产可用级别的代码。还有自动生成的交互式文档。
- 标准化：基于（并完全兼容）API 的相关开放标准：OpenAPI (以前被称为 Swagger) 和 JSON Schema。

2. FastAPI 特性:
- 基于开放标准：
  - 用于创建 API 的 OpenAPI 包含了路径操作，请求参数，请求体，安全性等的声明。
  - 使用 JSON Schema (因为 OpenAPI 本身就是基于 JSON Schema 的)自动生成数据模型文档。
  - 经过了缜密的研究后围绕这些标准而设计。并非狗尾续貂。
  - 这也允许了在很多语言中自动生成客户端代码。
- 自动生成文档：
  - 交互式 API 文档以及具探索性 web 界面。因为该框架是基于 OpenAPI，所以有很多可选项，FastAPI 默认自带两个交互式 API 文档。
  - Swagger UI，可交互式操作，能在浏览器中直接调用和测试你的 API 。
  - 另外的 API 文档：ReDoc
- 简洁：
  - 任何类型都有合理的默认值，任何和地方都有可选配置。所有的参数被微调，来满足你的需求，定义成你需要的 API。
  - 但是默认情况下，一切都能“顺利工作”。
- 验证：
  - 校验大部分（甚至所有？）的 Python 数据类型，包括：
    - JSON 对象 (dict).
    - JSON 数组 (list) 定义成员类型。
    - 字符串 (str) 字段, 定义最小或最大长度。
    - 数字 (int, float) 有最大值和最小值， 等等。
  - 校验外来类型， 比如:
    - URL.
    - Email.
    - UUID.
    - …及其他.
  - 所有的校验都由完善且强大的 Pydantic 处理。
- 安全性及身份验证：
  - 集成了安全性和身份认证。杜绝数据库或者数据模型的渗透风险。
  - OpenAPI 中定义的安全模式，包括：
    - HTTP 基本认证。
    - OAuth2 (也使用 JWT tokens)。在 OAuth2 with JWT查看教程。
    - API 密钥，在:
      - 请求头。
      - 查询参数。
      - Cookies, 等等。
  - 加上来自 Starlette（包括 session cookie）的所有安全特性。
  - 所有的这些都是可复用的工具和组件，可以轻松与你的系统，数据仓库，关系型以及 NoSQL 数据库等等集成。
- 依赖注入：
  - FastAPI 有一个使用非常简单，但是非常强大的依赖注入系统。
  - 甚至依赖也可以有依赖，创建一个层级或者图依赖。
  - 所有自动化处理都由框架完成。
  - 所有的依赖关系都可以从请求中获取数据，并且增加了路径操作约束和自动文档生成。
  - 即使在依赖项中被定义的路径操作 也会自动验证。
  - 支持复杂的用户身份认证系统，数据库连接等等。
  - 不依赖数据库，前端等。 但是和它们集成很简单。
- 无限制"插件"：
  - 或者说，导入并使用你需要的代码，而不需要它们。
  - 任何集成都被设计得被易于使用（用依赖关系），你可以用和路径操作相同的结构和语法，在两行代码中为你的应用创建一个“插件”。
- 测试：
  - 100% 测试覆盖。
  - 代码库100% 类型注释。
  - 用于生产应用。

3. Starlette 特性:
- FastAPI 和 Starlette 完全兼容(并基于)。所以，你有的其他的 Starlette 代码也能正常工作。FastAPI 实际上是 Starlette的一个子类。所以，如果你已经知道或者使用 Starlette，大部分的功能会以相同的方式工作。
- 通过 FastAPI 你可以获得所有 Starlette 的特性 ( FastAPI 就像加强版的 Starlette )：
  - 令人惊叹的性能。它是 Python 可用的最快的框架之一，和 NodeJS 及 Go 相当。
  - 支持 WebSocket 。
  - 支持 GraphQL 。
  - 后台任务处理。
  - Startup 和 shutdown 事件。
  - 测试客户端基于 HTTPX。
  - CORS, GZip, 静态文件, 流响应。
  - 支持 Session 和 Cookie 。
  - 100% 测试覆盖率。
  - 代码库 100% 类型注释。

4. Pydantic 特性:
- FastAPI 和 Pydantic 完全兼容(并基于)。所以，你有的其他的 Pydantic 代码也能正常工作。
- 兼容包括基于 Pydantic 的外部库， 例如用与数据库的 ORMs, ODMs。
- 这也意味着在很多情况下，你可以将从请求中获得的相同对象直接传到数据库，因为所有的验证都是自动的。
- 反之亦然，在很多情况下，你也可以将从数据库中获取的对象直接传到客户端。
- 通过 FastAPI 你可以获得所有 Pydantic (FastAPI 基于 Pydantic 做了所有的数据处理)：
  - 更简单：
    - 没有新的模式定义 micro-language 需要学习。
    - 如果你知道 Python types，你就知道如何使用 Pydantic。
  - 和你IDE/linter/brain适配:
    - 因为 pydantic 数据结构仅仅是你定义的类的实例；自动补全，linting，mypy 以及你的直觉应该可以和你验证的数据一起正常工作。
  - 更快：
    - 在 基准测试 中，Pydantic 比其他被测试的库都要快。
  - 验证复杂结构:
    - 使用分层的 Pydantic 模型, Python typing的 List 和 Dict 等等。
    - 验证器使我们能够简单清楚的将复杂的数据模式定义、检查并记录为 JSON Schema。
    - 你可以拥有深度嵌套的 JSON 对象并对它们进行验证和注释。
  - 可扩展:
    - Pydantic 允许定义自定义数据类型或者你可以用验证器装饰器对被装饰的模型上的方法扩展验证。
  - 100% 测试覆盖率。

5. 为什么要学 FastAPI:
- 最重要就是python香啊，用python能做很多数据处理，然后python的web框架也很多，但是像FastAPI这样灵活简洁的还是极少的。
- 学完就可以写很多接口了，主要就是写一些API。
- 网站开发还得是java…

====================================
原文链接：https://blog.jiumoz.com/archives/fastapi-cong-ru-men-dao-shi-zhan-0-chu-shi-fastapi

【多说一句】

FastAPI 和 Spring Boot 都是用于构建 web 应用的框架，但它们有一些显著的区别，主要体现在编程语言、设计理念和使用方式上。
以下是一些关键点的对比：

编程语言
    FastAPI：使用 Python 语言。
    Spring Boot：使用 Java 语言。
框架特性
    FastAPI：

        基于 Python 的类型提示和 Pydantic 模型进行数据验证和序列化。
        使用 ASGI（Asynchronous Server Gateway Interface）实现异步支持，性能优越。
        自动生成 OpenAPI 和 Swagger 文档。
        轻量级和易于使用，适合快速开发和原型设计。
    Spring Boot：

        基于 Java 的 Spring 框架，提供成熟的生态系统和丰富的功能。
        提供嵌入式服务器（如 Tomcat），无需单独部署应用服务器。
        支持多种配置和依赖注入，适合构建大型企业级应用。
        具有强大的社区支持和丰富的插件。
创建应用实例
    FastAPI：

    通过 FastAPI() 创建应用实例。
        示例：

            from fastapi import FastAPI

            app = FastAPI()

            @app.get("/")
            def read_root():
                return {"Hello": "World"}
    Spring Boot：

        使用注解和依赖注入创建应用实例。
            示例：

                import org.springframework.boot.SpringApplication;
                import org.springframework.boot.autoconfigure.SpringBootApplication;
                import org.springframework.web.bind.annotation.GetMapping;
                import org.springframework.web.bind.annotation.RestController;

                @SpringBootApplication
                public class DemoApplication {

                    public static void main(String[] args) {
                        SpringApplication.run(DemoApplication.class, args);
                    }
                }

                @RestController
                class HelloController {
                    @GetMapping("/")
                    public String index() {
                        return "Hello, World!";
                    }
                }
路由定义
        FastAPI：

        使用装饰器定义路由。
                示例：
                    @app.get("/items/{item_id}")
                    def read_item(item_id: int):
                        return {"item_id": item_id}

        Spring Boot：

            使用注解定义路由。
            示例：
                @RestController
                class ItemController {
                    @GetMapping("/items/{item_id}")
                    public Map<String, Integer> readItem(@PathVariable int item_id) {
                        return Collections.singletonMap("item_id", item_id);
                    }
                }
数据验证

    FastAPI：

        使用 Pydantic 模型进行数据验证。

            示例：
            from pydantic import BaseModel

            class Item(BaseModel):
                name: str
                price: float
                is_offer: bool = None

            @app.put("/items/{item_id}")
            def update_item(item_id: int, item: Item):
                return {"item_name": item.name, "item_id": item_id}

    Spring Boot：

        使用 Java Bean Validation（如 Hibernate Validator）进行数据验证。
            示例：
            import javax.validation.constraints.NotNull;
            import javax.validation.constraints.PositiveOrZero;

            class Item {
                @NotNull
                private String name;

                @PositiveOrZero
                private float price;

                private Boolean isOffer;

                // getters and setters
            }

            @PutMapping("/items/{item_id}")
            public Map<String, Object> updateItem(@PathVariable int item_id, @Valid @RequestBody Item item) {
                return Map.of("item_name", item.getName(), "item_id", item_id);
            }
总结
    虽然 FastAPI 和 Spring Boot 都是用于构建 web 应用的框架，但它们在语言、设计理念和具体实现上有很大的不同。
    选择哪个框架取决于你的项目需求、团队技能和个人偏好。如果你熟悉 Python 并且需要快速开发和原型设计，FastAPI 是一个很好的选择。
    如果你需要构建大型企业级应用并且熟悉 Java，Spring Boot 是一个强大的工具。
"""

# 先看一个例子

from typing import Union  # 导入 Union 类型，用于表示可以是多种类型之一

from fastapi import FastAPI  # 从 FastAPI 库中导入 FastAPI 类
from pydantic import BaseModel  # 从 Pydantic 库中导入 BaseModel 类，用于数据验证

# 创建一个 FastAPI 应用实例
app = FastAPI()


# 定义一个 Pydantic 模型，用于验证和解析请求体中的数据
class Item(BaseModel):
    name: str  # 商品名称，必须是字符串
    price: float  # 商品价格，必须是浮点数
    is_offer: Union[bool, None] = None  # 是否有优惠，可以是布尔类型或 None


# 定义一个根路径的 GET 请求处理函数
@app.get("/")
def read_root():
    return {"Hello": "World"}  # 返回一个 JSON 响应


# 定义一个带有路径参数的 GET 请求处理函数
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
    """
    读取指定 ID 的商品信息。

    参数:
    - item_id: 商品的唯一标识符，必须是整数。
    - q: 可选的查询参数，可以是字符串或 None。

    返回:
    - 包含 item_id 和 q 的 JSON 响应。
    """
    return {"item_id": item_id, "q": q}


# 定义一个带有路径参数的 PUT 请求处理函数，用于更新商品信息
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
    """
    更新指定 ID 的商品信息。

    参数:
    - item_id: 商品的唯一标识符，必须是整数。
    - item: 请求体中的商品信息，必须符合 Item 模型。

    返回:
    - 包含更新后商品名称和 ID 的 JSON 响应。
    """
    return {"item_name": item.name, "item_id": item_id}


"""
如何使用这个 FastAPI 应用程序：

1. 安装 FastAPI 和 Uvicorn：
   使用 pip 安装 FastAPI 和 Uvicorn（ASGI 服务器）： pip install fastapi uvicorn


2. 运行应用程序：
在终端中运行以下命令启动 Uvicorn 服务器：uvicorn main:app --reload

这里 `main` 是你的 Python 文件名（不带 .py 后缀），`app` 是 FastAPI 实例的名称，
`--reload` 标志用于在代码更改时自动重新启动服务器。
你可以先把put的代码注释掉，运行起来，然后把注释去掉，它会自己部署更新。

3. 访问 API 端点：
- 打开浏览器，访问 http://127.0.0.1:8000/，你会看到 {"Hello": "World"}。
- 访问 http://127.0.0.1:8000/items/1?q=test，返回 {"item_id": 1, "q": "test"}。
- 访问 http://127.0.0.1:8000/docs，查看自动生成的 API 文档。你可以在这里测试 API 端点。

4. 更新商品信息：
使用 PUT 请求更新商品信息，例如：
PUT http://127.0.0.1:8000/items/1
请求体：
    {
    "name": "New Item",
    "price": 10.5,
    "is_offer": true
    }
返回：
    {
    "item_name": "New Item",
    "item_id": 1
    }


这个应用程序展示了如何使用 FastAPI 创建简单的 API 端点，包括 GET 和 PUT 请求。你可以根据需要扩展这些端点，并添加更多的功能。
"""
